
data Action = N | S | E | W | L | R | F deriving (Show, Eq)
data Instruction = Instruction Action Double deriving (Show)

type Position = (Double, Double)
type WayPoint = (Double, Double)
type Angle = Double
data Ship = Ship WayPoint Position deriving (Show)

parseAction :: Char -> Action
parseAction c = case c of 
    'N' -> N
    'S' -> S
    'E' -> E
    'W' -> W
    'L' -> L
    'R' -> R
    'F' -> F
 
parseInstruction :: String -> Instruction
parseInstruction string = 
    Instruction (parseAction action) (read value)
    where
        action = head string
        value = tail string 

parseInput :: String -> [Instruction]
parseInput = map parseInstruction . lines

angleToRadian :: Double -> Double
angleToRadian angle = (pi / 180) * angle

leftRotate :: WayPoint -> Angle -> WayPoint
leftRotate (wx, wy) angle = case angle of
    90.0  -> (-wy, wx)
    180.0 -> (-wx, -wy)
    270.0 -> (wy, -wx)
    360.0 -> (wx, wy)

rightRotate :: WayPoint -> Angle -> WayPoint
rightRotate (wx, wy) angle = case angle of
    90.0  -> (wy, -wx)
    180.0 -> (-wx, -wy)
    270.0 -> (-wy, wx)
    360.0 -> (wx, wy)

move :: Ship -> Instruction -> Ship
move (Ship wp@(wx, wy) (px, py)) (Instruction action value) = 
    case action of
        N -> Ship (wx, wy+value) (px, py)
        S -> Ship (wx, wy-value) (px, py)
        E -> Ship (wx+value, wy) (px, py)
        W -> Ship (wx-value, wy) (px, py)
        L -> Ship (leftRotate wp value) (px, py)
        R -> Ship (rightRotate wp value) (px, py)
        F -> Ship (wx, wy) (px+dx, py+dy)
            where
                dx = value * wx
                dy = value * wy
                
manhattanDistance :: Ship -> Double
manhattanDistance (Ship _ (x, y)) = abs x + abs y

main :: IO ()
main = do
    input <- readFile "input.txt"
    print . manhattanDistance 
          . foldl move (Ship (10, 1) (0, 0)) 
          . parseInput $ input
            